<!DOCTYPE html>
<html lang="zh-CN">
  <head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <meta name="description" content="">
  <meta name="keywords" content="">
  
    <link rel="icon" href="/avatar.jpg">
  
    
  <title>HDU-4825 Xor Sum（OJ 优化实验） | 科学君的不科学博客</title>
  <link rel="stylesheet" href="/style.css">
  <link rel="stylesheet" href="/lib/jquery.fancybox.min.css">
  <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
  <script type="text/javascript" src="https://tajs.qq.com/stats?sId=65546304" charset="UTF-8"></script>
  <script>
  (function(){
      var bp = document.createElement('script');
      var curProtocol = window.location.protocol.split(':')[0];
      if (curProtocol === 'https') {
          bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
      }
      else {
          bp.src = 'http://push.zhanzhang.baidu.com/push.js';
      }
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(bp, s);
  })();
  </script>
</head>

<body>
  <header>
  <div class="header-container">
    <a class='logo' href="/">
      <span>科学君的不科学博客</span>
    </a>
    <ul class="right-header">
      
        <li class="nav-item">
          
            <a href="/" class="item-link">首页</a>
          
        </li>
      
        <li class="nav-item">
          
            <a href="/about" class="item-link">关于</a>
          
        </li>
      
        <li class="nav-item">
          
            <a href="/archives" class="item-link">归档</a>
          
        </li>
      
        <li class="nav-item">
          
            <a href="/tags" class="item-link">标签</a>
          
        </li>
      
        <li class="nav-item">
          
            <a href="/atom.xml" class="item-link">FEED 订阅</a>
          
        </li>
      
    </ul>
  </div>
</header>

  <main id='post'>
  <div class="content">
    <article>
      <section class="content markdown-body">
        <h1>HDU-4825 Xor Sum（OJ 优化实验）</h1>
        <div class='post-meta'>
          <i class="fa fa-calendar" aria-hidden="true"></i>
          <time>2016年07月25日</time>
          
          | <i class="fa fa-folder-open-o" aria-hidden="true"></i> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/acm/">acm</a>
  </div>



          
          
          |
          
          <i class="fa fa-tag" aria-hidden="true"></i>
          
          
  <a href="/tags/#acm" class='tag'>acm</a>


          
        </div>
        <ul>
<li><a href="#sec-">题目：</a></li>
<li><a href="#sec-">解析&amp;吐槽：</a><ul>
<li><a href="#sec-">提交语言：c++ vs g++</a></li>
<li><a href="#sec-">堆分配 vs 栈分配</a></li>
<li><a href="#sec-">递归 vs 非递归</a></li>
<li><a href="#sec-">cin&amp;cout vs scanf&amp;printf</a></li>
</ul>
</li>
<li><a href="#sec-">总结</a></li>
<li><a href="#sec-">16 年 8 月 20 日更新</a></li>
</ul>
<h1 id="题目："><a href="#题目：" class="headerlink" title="题目："></a>题目：<a id="sec-"></a></h1><p class="verse"><br>Xor Sum<br><br>Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)<br><br>Total Submission(s): 1330    Accepted Submission(s): 561<br><br><br><br><br><br>Problem Description<br><br>Zeus 和 Prometheus 做了一个游戏，Prometheus 给 Zeus 一个集合，集合中包含了 N 个正整数，随后 Prometheus 将向 Zeus 发起 M 次询问，每次询问中包含一个正整数 S，之后 Zeus 需要在集合当中找出一个正整数 K，使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大，随即同意 Zeus 可以向人类求助。你能证明人类的智慧么？<br><br><br><br><br><br>Input<br><br>输入包含若干组测试数据，每组测试数据包含若干行。<br><br>输入的第一行是一个整数 T（T &lt; 10），表示共有 T 组数据。<br><br>每组数据的第一行输入两个正整数 N，M（&lt;1=N,M&lt;=100000），接下来一行，包含 N 个正整数，代表 Zeus 的获得的集合，之后 M 行，每行一个正整数 S，代表 Prometheus 询问的正整数。所有正整数均不超过 2^32。<br><br><br><br><br><br>Output<br><br>对于每组数据，首先需要输出单独一行”Case #?:”，其中问号处应填入当前的数据组数，组数从 1 开始计算。<br><br>对于每个询问，输出一个正整数 K，使得 K 与 S 异或值最大。<br><br><br><br><br><br>Sample Input<br><br><br><br>2<br><br>3 2<br><br>3 4 5<br><br>1<br><br>5<br><br>4 1<br><br>4 6 5 6<br><br>3<br><br><br><br><br><br><br><br>Sample Output<br><br><br><br>Case #1:<br><br>4<br><br>3<br><br>Case #2:<br><br>4<br><br></p>

<h1 id="解析-amp-吐槽："><a href="#解析-amp-吐槽：" class="headerlink" title="解析&amp;吐槽："></a>解析&amp;吐槽：<a id="sec-"></a></h1><p>这次的主题是优化实验，就把代码放在下面了。</p>
<p>这道题用字典树就可以做，就是道水题，但是我在这道题上面试验了很多优化代码的方法，把运行时间从 951ms 降到了 280ms。</p>
<h2 id="提交语言：c-vs-g"><a href="#提交语言：c-vs-g" class="headerlink" title="提交语言：c++ vs g++"></a>提交语言：c++ vs g++<a id="sec-"></a></h2><p>这两个是用不同编译器编译的。顾名思义，g++指的是 GNU G++；而 c++则是 VC++，微软的编译器。 大部分的时候，用哪个编译器都是一样的，但是会在运行时间和内存占用上有不少的区别，很多时候 这个区别就是你是否能 AC 的关键。在我们学校的 acm 群中，不止一次有同学提到有些题用 c++交 可以过，但是 g++就会爆内存。我在这道题中遇到的问题则是 c++超时，g++勉强能过。贴上第一次 ac 的代码，耗时：951ms，内存占用：56840KB。为节约空间起见我就不写 include 和 namespace 了。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">ct</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    ct *L[<span class="number">2</span>];</span><br><span class="line">    ct() &#123;</span><br><span class="line">        L[<span class="number">0</span>] = L[<span class="number">1</span>] = <span class="literal">nullptr</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    ct(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span> &amp;s,<span class="keyword">int</span> i) &#123;</span><br><span class="line">        L[<span class="number">0</span>] = L[<span class="number">1</span>] = <span class="literal">nullptr</span>;</span><br><span class="line">        <span class="keyword">if</span> (i&gt;=<span class="number">32</span>)</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">this</span>-&gt;ins(s,i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//~ct() &#123;</span></span><br><span class="line">    <span class="comment">//	for (int i = 0;i &lt; 2;++i)</span></span><br><span class="line">    <span class="comment">//		if (L[i])</span></span><br><span class="line">    <span class="comment">//			delete L[i];</span></span><br><span class="line">    <span class="comment">//&#125;</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">ins</span><span class="params">(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s,<span class="keyword">int</span> i)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (i &lt; <span class="number">32</span>) &#123;</span><br><span class="line">            ct*&amp; nw = L[(s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>];</span><br><span class="line">            <span class="keyword">if</span> (nw)</span><br><span class="line">                nw-&gt;ins(s,i+<span class="number">1</span>);</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                nw = <span class="keyword">new</span> ct(s,i+<span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="title">query</span><span class="params">(ct* c, <span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s, <span class="keyword">int</span> i, <span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; have)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (i &gt;= <span class="number">32</span>)</span><br><span class="line">        <span class="keyword">return</span> have;</span><br><span class="line"></span><br><span class="line">    ct* nw = c-&gt;L[(s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>];</span><br><span class="line">    <span class="keyword">if</span> (nw)</span><br><span class="line">        <span class="keyword">return</span> query(nw, s, i + <span class="number">1</span>, (have &lt;&lt; <span class="number">1</span>) + ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>));</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="keyword">return</span> query(c-&gt;L[<span class="number">1</span> - ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>)],</span><br><span class="line">            s, i + <span class="number">1</span>, (have &lt;&lt; <span class="number">1</span>) + <span class="number">1</span> - ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    ios::sync_with_stdio(<span class="literal">false</span>);</span><br><span class="line">    <span class="built_in">cin</span>.tie(<span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> T;</span><br><span class="line">    <span class="built_in">cin</span> &gt;&gt; T;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> k = <span class="number">1</span>;k &lt;= T;++k)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">cout</span> &lt;&lt; <span class="string">"Case #"</span> &lt;&lt; k &lt;&lt; <span class="string">":"</span> &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line">        <span class="keyword">int</span> n, m;</span><br><span class="line">        <span class="built_in">cin</span> &gt;&gt; n &gt;&gt; m;</span><br><span class="line"></span><br><span class="line">        ct t;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (n--)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">unsigned</span> <span class="keyword">long</span> a;</span><br><span class="line">            <span class="built_in">cin</span> &gt;&gt; a;</span><br><span class="line"></span><br><span class="line">            t.ins(a, <span class="number">0</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (m--)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">unsigned</span> <span class="keyword">long</span> a;</span><br><span class="line">            <span class="built_in">cin</span> &gt;&gt; a;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//bitset&lt;32&gt; b(~a);</span></span><br><span class="line">            <span class="comment">//string bstr = b.to_string();</span></span><br><span class="line">            <span class="comment">//cout &lt;&lt; "debug: " &lt;&lt; query(&amp;t, string(32 - bstr.size(), '0') + bstr, "") &lt;&lt; endl; //debug</span></span><br><span class="line">            <span class="comment">//b = bitset&lt;32&gt;(query(&amp;t, string(32 - bstr.size(), '0') + bstr, 0, ""));</span></span><br><span class="line"></span><br><span class="line">            <span class="built_in">cout</span> &lt;&lt; query(&amp;t, ~a, <span class="number">0</span>, <span class="number">0</span>) &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在这里我本来是用 bitset 把数字转换成 2 进制的字符串然后让函数处理的，结果频繁地创建字符串 严重降低了代码的运行效率，最后还是改用位运算了。</p>
<h2 id="堆分配-vs-栈分配"><a href="#堆分配-vs-栈分配" class="headerlink" title="堆分配 vs 栈分配"></a>堆分配 vs 栈分配<a id="sec-"></a></h2><p>在前面的代码中，我通过 new 在堆上分配内存，而这种行为本来就很慢，因为堆中的内存不是连续的， 如果程序想要分配一段内存，就不得不在堆上寻找可以容纳这个对象的空间。上面的代码中我注释掉了 释放内存的代码，节省了释放时间，但是仍然差点超时。不过和后面相比内存倒是没超过多少，真是神奇。</p>
<p>然后我把代码改成了在栈上分配空间，一开始开一个数组来存储所有的对象，用 idx 表示数组的尾部， 每次将新产生的对象插入到 idx 的位置，分配空间的时间复杂度降为了 O(1)。改动的内容比较少， 只要把指针改成索引，new 改成++idx 即可。</p>
<p>此外还必须注意一些语法的问题，数组的声明必须放在 struct 的完整声明之后，否则编译器无法推断出 数组的大小，会报错，因此我们只好把用到数组的 ins 函数的声明放进 struct 里面，定义放在数组声明后面。 还有我们不知道最多需要多少节点，所以只好把数组尽量往大了开了。尽管这道题只需要二叉树，但是我们 没法用二叉树组的方法（就是子节点索引等于父节点索引*2 加 1 或者 0 的那个），因为存储的是 32 位的 无符号整数，二叉树至少需要 33 层，就需要 2^33 个节点，我们开不到这么大的数组。</p>
<p>此代码 c++仍然超时，但 g++耗时为 577ms，内存占用：32960KB，效率有了巨大的提高。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">ct</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">int</span> L[<span class="number">2</span>];</span><br><span class="line">    ct() &#123;</span><br><span class="line">        L[<span class="number">0</span>] = L[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    ct(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span> &amp;s, <span class="keyword">int</span> i) &#123;</span><br><span class="line">        L[<span class="number">0</span>] = L[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">if</span> (i &gt;= <span class="number">32</span>)</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">this</span>-&gt;ins(s, i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">ins</span><span class="params">(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s, <span class="keyword">int</span> i)</span></span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">ct heap[<span class="number">1000000</span> &lt;&lt; <span class="number">2</span>];</span><br><span class="line"><span class="keyword">int</span> idx = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">inline</span> <span class="keyword">void</span> ct::ins(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s, <span class="keyword">int</span> i) &#123;</span><br><span class="line">    <span class="keyword">if</span> (i &lt; <span class="number">32</span>) &#123;</span><br><span class="line">        <span class="keyword">int</span>&amp; nw = L[(s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">if</span> (nw) &#123;</span><br><span class="line">            heap[nw].ins(s, i + <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> &#123;</span><br><span class="line">            nw = idx;</span><br><span class="line">            ++idx;</span><br><span class="line">            heap[nw] = ct(s, i + <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="title">query</span><span class="params">(ct* c, <span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s, <span class="keyword">int</span> i, <span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; have)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (i &gt;= <span class="number">32</span>)</span><br><span class="line">        <span class="keyword">return</span> have;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> nw = c-&gt;L[(s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>];</span><br><span class="line">    <span class="keyword">if</span> (nw)</span><br><span class="line">        <span class="keyword">return</span> query(&amp;heap[nw], s, i + <span class="number">1</span>, (have &lt;&lt; <span class="number">1</span>) + ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>));</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="keyword">return</span> query(&amp;heap[c-&gt;L[<span class="number">1</span> - ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>)]],</span><br><span class="line">            s, i + <span class="number">1</span>, (have &lt;&lt; <span class="number">1</span>) + <span class="number">1</span> - ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    ios::sync_with_stdio(<span class="literal">false</span>);</span><br><span class="line">    <span class="built_in">cin</span>.tie(<span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> T;</span><br><span class="line">    <span class="built_in">cin</span> &gt;&gt; T;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> k = <span class="number">1</span>;k &lt;= T;++k)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">cout</span> &lt;&lt; <span class="string">"Case #"</span> &lt;&lt; k &lt;&lt; <span class="string">":"</span> &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line">        <span class="keyword">int</span> n, m;</span><br><span class="line">        <span class="built_in">cin</span> &gt;&gt; n &gt;&gt; m;</span><br><span class="line">        idx = <span class="number">1</span>;</span><br><span class="line">        heap[<span class="number">0</span>] = ct();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (n--)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">unsigned</span> <span class="keyword">long</span> a;</span><br><span class="line">            <span class="built_in">cin</span> &gt;&gt; a;</span><br><span class="line"></span><br><span class="line">            heap[<span class="number">0</span>].ins(a, <span class="number">0</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (m--)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">unsigned</span> <span class="keyword">long</span> a;</span><br><span class="line">            <span class="built_in">cin</span> &gt;&gt; a;</span><br><span class="line"></span><br><span class="line">            <span class="built_in">cout</span> &lt;&lt; query(heap, ~a, <span class="number">0</span>, <span class="number">0</span>) &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="递归-vs-非递归"><a href="#递归-vs-非递归" class="headerlink" title="递归 vs 非递归"></a>递归 vs 非递归<a id="sec-"></a></h2><p>可以看到，前面的代码是使用递归来处理数据的，如果改成循环会怎么样呢？我们做一下实验。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">ct</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">int</span> L[<span class="number">2</span>];</span><br><span class="line">    ct() &#123;</span><br><span class="line">        L[<span class="number">0</span>] = L[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">ct heap[<span class="number">1000000</span> &lt;&lt; <span class="number">2</span>];</span><br><span class="line"><span class="keyword">int</span> idx = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">void</span> <span class="title">insert</span><span class="params">(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s)</span> </span>&#123;</span><br><span class="line">    ct *c = heap;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>;i &lt; <span class="number">32</span>;++i) &#123;</span><br><span class="line">        <span class="keyword">int</span>&amp; nw = c-&gt;L[(s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">if</span> (!nw) &#123;</span><br><span class="line">            nw = idx;</span><br><span class="line">            ++idx;</span><br><span class="line">            heap[nw] = ct();</span><br><span class="line">        &#125;</span><br><span class="line">        c = &amp;heap[nw];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="title">query</span><span class="params">(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">unsigned</span> have = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">    ct *c = heap;</span><br><span class="line">    <span class="keyword">while</span> (i &lt; <span class="number">32</span>) &#123;</span><br><span class="line">        <span class="keyword">int</span> nw = c-&gt;L[(s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">if</span> (nw) &#123;</span><br><span class="line">            c = &amp;heap[nw];</span><br><span class="line">            have = (have &lt;&lt; <span class="number">1</span>) + ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> &#123;</span><br><span class="line">            c = &amp;heap[c-&gt;L[<span class="number">1</span> - ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>)]];</span><br><span class="line">            have = (have &lt;&lt; <span class="number">1</span>) + <span class="number">1</span> - ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        ++i;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> have;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    ios::sync_with_stdio(<span class="literal">false</span>);</span><br><span class="line">    <span class="built_in">cin</span>.tie(<span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> T;</span><br><span class="line">    <span class="built_in">cin</span> &gt;&gt; T;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> k = <span class="number">1</span>;k &lt;= T;++k)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">cout</span> &lt;&lt; <span class="string">"Case #"</span> &lt;&lt; k &lt;&lt; <span class="string">":"</span> &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line">        <span class="keyword">int</span> n, m;</span><br><span class="line">        <span class="built_in">cin</span> &gt;&gt; n &gt;&gt; m;</span><br><span class="line">        idx = <span class="number">1</span>;</span><br><span class="line">        heap[<span class="number">0</span>] = ct();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (n--)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">unsigned</span> <span class="keyword">long</span> a;</span><br><span class="line">            <span class="built_in">cin</span> &gt;&gt; a;</span><br><span class="line"></span><br><span class="line">            insert(a);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (m--)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">unsigned</span> <span class="keyword">long</span> a;</span><br><span class="line">            <span class="built_in">cin</span> &gt;&gt; a;</span><br><span class="line"></span><br><span class="line">            <span class="built_in">cout</span> &lt;&lt; query(~a) &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>代码使用 g++编译，耗时 405 MS，内存消耗 32936 KB。c++仍然超时。可见把递归 改成循环可以提高一定的效率，但在本题效果不大（只减少了 172ms）</p>
<h2 id="cin-amp-cout-vs-scanf-amp-printf"><a href="#cin-amp-cout-vs-scanf-amp-printf" class="headerlink" title="cin&amp;cout vs scanf&amp;printf"></a>cin&amp;cout vs scanf&amp;printf<a id="sec-"></a></h2><p>众所周知，cin 的效率比 scanf 低了不止一点，因为 cin 会与 c 语言的输入输出函数自动同步， 每次 cin 读取都会刷新缓冲区来防止其与 scanf 混合使用时产生错误。但我们可以通过下列 语句来取消同步：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ios::sync_with_stdio(<span class="literal">false</span>);</span><br><span class="line"><span class="built_in">cin</span>.tie(<span class="literal">NULL</span>);</span><br></pre></td></tr></table></figure>
<p>加上这个语句之后大部分只有 scanf 能过的题 cin 也能过了，但是仍然有少部分题会卡时间。 这里，我们把输入改成 scanf，输出仍然使用 cout，但是不使用 endl 来刷新缓冲区，而是 输出 <code>\n</code> 来换行。本来 oj 的输入和输出就是固定的，什么时候刷新输出缓冲区对输入没有 影响，这么做之后程序会在结束的时候刷新缓冲区输出内容。</p>
<p>| 编译器 | 耗时 | 内存消耗 |<br>| g++ | 327 | 32932 |<br>| c++ | 561 | 33096 |</p>
<p>顺带一提，如果不加上那两行代码，使用 endl 来换行的话，g++耗时是 561ms。</p>
<p>在全部改成 scanf 和 printf 之后，耗时如下：</p>
<p>| 编译器 | 耗时 | 内存消耗 |<br>| g++ | 280 | 32708 |<br>| c++ | 374 | 33096 |</p>
<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结<a id="sec-"></a></h1><p>貌似 c++对于递归的优化不大好，在这道题使用递归时 c++永远是超时的。其他时候 c++与 g++差不多， 但效率总是低一些。</p>
<p>而堆分配内存会极大地拖慢运行速度，改成栈分配之后无论是分配效率还是删除效率都会提高很多，删除 的时候只需要把索引重新移到 1 的位置即可。另外，结构体中存储的子节点位置 不一定是索引，和堆内存时一样 存储指针也是行的，索引只需要在分配一个新的对象时使用即可。</p>
<p>最终的代码：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br></pre></td><td class="code"><pre><span class="line">  <span class="comment">// oj.cpp : 定义控制台应用程序的入口点。</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//#include &lt;iostream&gt;</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;limits&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;algorithm&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;numeric&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;utility&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sstream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cctype&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cmath&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;functional&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;deque&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stack&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;bitset&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">ct</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">int</span> L[<span class="number">2</span>];</span><br><span class="line">    ct() &#123;</span><br><span class="line">        L[<span class="number">0</span>] = L[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">ct heap[<span class="number">1000000</span> &lt;&lt; <span class="number">2</span>];</span><br><span class="line"><span class="keyword">int</span> idx = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">void</span> <span class="title">insert</span><span class="params">(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s)</span> </span>&#123;</span><br><span class="line">    ct *c = heap;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>;i &lt; <span class="number">32</span>;++i) &#123;</span><br><span class="line">        <span class="keyword">int</span>&amp; nw = c-&gt;L[(s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">if</span> (!nw) &#123;</span><br><span class="line">            nw = idx;</span><br><span class="line">            ++idx;</span><br><span class="line">            heap[nw] = ct();</span><br><span class="line">        &#125;</span><br><span class="line">        c = &amp;heap[nw];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="title">query</span><span class="params">(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">unsigned</span> have = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">    ct *c = heap;</span><br><span class="line">    <span class="keyword">while</span> (i &lt; <span class="number">32</span>) &#123;</span><br><span class="line">        <span class="keyword">int</span> nw = c-&gt;L[(s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">if</span> (nw) &#123;</span><br><span class="line">            c = &amp;heap[nw];</span><br><span class="line">            have = (have &lt;&lt; <span class="number">1</span>) + ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> &#123;</span><br><span class="line">            c = &amp;heap[c-&gt;L[<span class="number">1</span> - ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>)]];</span><br><span class="line">            have = (have &lt;&lt; <span class="number">1</span>) + <span class="number">1</span> - ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        ++i;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> have;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line"><span class="comment">//	ios::sync_with_stdio(false);</span></span><br><span class="line"><span class="comment">//	cin.tie(NULL);</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> T;</span><br><span class="line">    <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &amp;T);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> k = <span class="number">1</span>;k &lt;= T;++k)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">//cout &lt;&lt; "Case #" &lt;&lt; k &lt;&lt; ":" &lt;&lt; endl;</span></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Case #%d:\n"</span>, k);</span><br><span class="line">        <span class="keyword">int</span> n, m;</span><br><span class="line">        <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &amp;n, &amp;m);</span><br><span class="line">        idx = <span class="number">1</span>;</span><br><span class="line">        heap[<span class="number">0</span>] = ct();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (n--)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">unsigned</span> <span class="keyword">long</span> a;</span><br><span class="line">            <span class="built_in">scanf</span>(<span class="string">"%lu"</span>, &amp;a);</span><br><span class="line"></span><br><span class="line">            insert(a);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (m--)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">unsigned</span> <span class="keyword">long</span> a;</span><br><span class="line">            <span class="built_in">scanf</span>(<span class="string">"%lu"</span>, &amp;a);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//cout &lt;&lt; query(~a) &lt;&lt; endl;</span></span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"%lu\n"</span>, query(~a));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="16-年-8-月-20-日更新"><a href="#16-年-8-月-20-日更新" class="headerlink" title="16 年 8 月 20 日更新"></a>16 年 8 月 20 日更新<a id="sec-"></a></h1><p>最近发现了一个新的提升读取速度的方法：fread。</p>
<p>这是一个 c 语言函数，具体作用是把 n 个字符作为字符串一次性读入。根据 <a href="http://www.bkjia.com/ASPjc/951313.html" target="_blank" rel="noopener">这里</a> 的说法，它可以把读取时间 效率再提高十倍。</p>
<p>在那篇文章中，fread 被用来读取文件，由于 oj 实际上是把文件重定向到标准 io 来实现输入的，所以 我们必须把它再映射回去才能实现从标准 io 输入。然后我们再手动把字符串转换成数字即可，这里的 转换操作最好不要使用 <code>stringstream</code> ，因为创建字符串流的过程会将字符串中的内容复制进一个 string 中，这个过程涉及到拷贝和堆的内存分配，耗时很多，还会多占用 2 倍的内存。</p>
<p>以下是我的实际处理过程：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> MAXBUF = <span class="number">1000000</span> &lt;&lt; <span class="number">2</span>;</span><br><span class="line"><span class="keyword">char</span> buf[MAXBUF];</span><br><span class="line"><span class="keyword">char</span>* startpoint = buf; <span class="comment">//字符串的读取起点</span></span><br></pre></td></tr></table></figure>
<p>buf 是一个字符数组，用来存储读入的数据，程序开始的时候会把所有输入都读取到这个地方。 startpoint 表示读取的起点，下面的函数会使用它。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">void</span> <span class="title">sread</span><span class="params">(T &amp;res)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (;*startpoint;++startpoint)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (*startpoint == <span class="string">' '</span> || *startpoint == <span class="string">'\n'</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            ++startpoint;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            res = res * <span class="number">10</span> + *startpoint - <span class="string">'0'</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这个函数用来在 buf 数组中读取数据，类似于 scanf，每次调用会从 buf 中读取一个数据填充到 res 中，并且以空白符为分隔。但是这里每次只能读取一个数据，而且只能读取十进制数字。这个 函数使用指针 startpoint 来表示读取的起点，每次从这里读取并且将 startpoint 设置到下一个 数据的开头（目前还没法处理连续两个分隔符的情况）。</p>
<p>在 main 函数中的读取操作：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> len = fread(buf, <span class="number">1</span>, MAXBUF, <span class="built_in">stdin</span>);</span><br><span class="line"><span class="keyword">if</span> (len &gt;= MAXBUF)</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">int</span>();</span><br><span class="line">buf[len] = <span class="string">'\0'</span>;</span><br></pre></td></tr></table></figure>
<p>fread 函数的第一个参数是读取到的数据的存储位置，第二个是读取的单个数据的字节数，由于 是 char，所以这里填 1；第三个是最多读取多少数据，这里填上数组的大小，总不能越界不是(´･ω･`)。 第四个参数是重点：输入流。如果从文件读取的话，这里要填上一个 FILE 指针，但我们要从标准 io 读入，所以写 stdin——标准输入流。当 fread 读满 MAXBUF 个字符或者读取到 EOF 的时候（别忘了 oj 是从文件映射到标准输入的，所以最后一定会有 EOF），就会终止输入，并且返回读取的字符数。</p>
<p>后面的两行是为了确保 fread 读取了全部的输入。如果 buf 被读取满了的话，很可能没有完整读入 所有的输入，这里会抛出一个异常，在 oj 的结果页面可以看到一个 RE（如果你用的是 PC^2，很 可能会得到一个 CE，貌似有些情况下 pc^2 会把 RE 当成 CE），这总比因为读入不完整而得到其他 的奇怪结果要强得多，问题是很容易定位的。</p>
<p>然后把最后一个位置赋成 <code>&#39;\0&#39;</code> ，表示字符串的结尾，这样对于以 EOF 结束输入的题比较有用。</p>
<p>最后使用 sread 读取就可以了。</p>
<p>经过测试，现在的耗时是 234ms，又缩短了 46ms。</p>
<p>最终代码（应该是吧）：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// oj.cpp : ??????????????</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//#include &lt;iostream&gt;</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdio&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;limits&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;algorithm&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;numeric&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;utility&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstdlib&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sstream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cctype&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cmath&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;functional&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;deque&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stack&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;bitset&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">ct</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="keyword">int</span> L[<span class="number">2</span>];</span><br><span class="line">    ct() &#123;</span><br><span class="line">        L[<span class="number">0</span>] = L[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">ct heap[<span class="number">1000000</span> &lt;&lt; <span class="number">2</span>];</span><br><span class="line"><span class="keyword">int</span> idx = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">void</span> <span class="title">insert</span><span class="params">(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s)</span> </span>&#123;</span><br><span class="line">    ct *c = heap;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>;i &lt; <span class="number">32</span>;++i) &#123;</span><br><span class="line">        <span class="keyword">int</span>&amp; nw = c-&gt;L[(s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">if</span> (!nw) &#123;</span><br><span class="line">            nw = idx;</span><br><span class="line">            ++idx;</span><br><span class="line">            heap[nw] = ct();</span><br><span class="line">        &#125;</span><br><span class="line">        c = &amp;heap[nw];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="title">query</span><span class="params">(<span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">long</span>&amp; s)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">unsigned</span> have = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">    ct *c = heap;</span><br><span class="line">    <span class="keyword">while</span> (i &lt; <span class="number">32</span>) &#123;</span><br><span class="line">        <span class="keyword">int</span> nw = c-&gt;L[(s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>];</span><br><span class="line">        <span class="keyword">if</span> (nw) &#123;</span><br><span class="line">            c = &amp;heap[nw];</span><br><span class="line">            have = (have &lt;&lt; <span class="number">1</span>) + ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> &#123;</span><br><span class="line">            c = &amp;heap[c-&gt;L[<span class="number">1</span> - ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>)]];</span><br><span class="line">            have = (have &lt;&lt; <span class="number">1</span>) + <span class="number">1</span> - ((s &gt;&gt; (<span class="number">31</span> - i)) &amp; <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        ++i;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> have;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> MAXBUF = <span class="number">1000000</span> &lt;&lt; <span class="number">2</span>;</span><br><span class="line"><span class="keyword">char</span> buf[MAXBUF];</span><br><span class="line"><span class="keyword">char</span>* startpoint = buf; <span class="comment">//????????</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="keyword">void</span> <span class="title">sread</span><span class="params">(T &amp;res)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (;*startpoint;++startpoint)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (*startpoint == <span class="string">' '</span> || *startpoint == <span class="string">'\n'</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            ++startpoint;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            res = res * <span class="number">10</span> + *startpoint - <span class="string">'0'</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">//  ios::sync_with_stdio(false);</span></span><br><span class="line">    <span class="comment">//  cin.tie(NULL);</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> len = fread(buf, <span class="number">1</span>, MAXBUF, <span class="built_in">stdin</span>);</span><br><span class="line">    <span class="comment">//int len = fread(buf, 1, MAXBUF, fopen("oj.in", "r")); //debug</span></span><br><span class="line">    <span class="keyword">if</span> (len &gt;= MAXBUF)</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">int</span>();</span><br><span class="line">    buf[len] = <span class="string">'\0'</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> T;</span><br><span class="line">    sread(T);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> k = <span class="number">1</span>;k &lt;= T;++k)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">//cout &lt;&lt; "Case #" &lt;&lt; k &lt;&lt; ":" &lt;&lt; endl;</span></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Case #%d:\n"</span>, k);</span><br><span class="line">        <span class="keyword">int</span> n, m;</span><br><span class="line">        sread(n);</span><br><span class="line">        sread(m);</span><br><span class="line">        idx = <span class="number">1</span>;</span><br><span class="line">        heap[<span class="number">0</span>] = ct();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (n--)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">unsigned</span> <span class="keyword">long</span> a;</span><br><span class="line">            sread(a);</span><br><span class="line"></span><br><span class="line">            insert(a);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (m--)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">unsigned</span> <span class="keyword">long</span> a;</span><br><span class="line">            sread(a);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//cout &lt;&lt; query(~a) &lt;&lt; endl;</span></span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"%lu\n"</span>, query(~a));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>有趣的是，目前在 VJ 中这道题的所有提交里面，耗时最少和耗时最多的人都是我_(:зゝ∠)_</p>

      </section>
      <div class="license">
        <a href="http://creativecommons.org/licenses/by-sa/3.0/" rel="license" target="_blank">
          <img src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" style="border-width:0"
               alt="Creative Commons License" class="center">
        </a>
      </div>
      <p>
        本作品采用
        <a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" target="_blank">
          署名-相同方式共享 4.0 国际
        </a>
        进行许可。欢迎转载、使用、重新发布，但务必保留文章署名
        “不科学的科学君” (Liu233w) 与博客链接：
        <a href="https://liu233w.github.io">https://liu233w.github.io</a>
        ，基于本文修改后的作品务必以相同的许可发布。如有任何疑问，请
        <a href="mailto:wwwlsmcom@outlook.com" target="_blank">与我联系</a>
        。
      </p>
    </article>
    
    <!-- disqus 评论框 start -->
    <div class="comment">
      <div id="disqus_thread" class="disqus-thread">
        <i>加载评论框需要翻墙</i>
      </div>
    </div>
    <!-- disqus 评论框 end -->
    
    
    <!-- livere 评论框 start -->
    <div class="comment">
      <div id="lv-container" data-id="city" data-uid="MTAyMC8zNTE5NS8xMTczMA=="></div>
    </div>
    <!-- livere 评论框 end -->
    
  </div>
  <aside>
    
    <div class="toc-container">
      <h1>目录</h1>
      <div class="content">
        <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#题目："><span class="toc-number">1.</span> <span class="toc-text">题目：</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#解析-amp-吐槽："><span class="toc-number">2.</span> <span class="toc-text">解析&amp;吐槽：</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#提交语言：c-vs-g"><span class="toc-number">2.1.</span> <span class="toc-text">提交语言：c++ vs g++</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#堆分配-vs-栈分配"><span class="toc-number">2.2.</span> <span class="toc-text">堆分配 vs 栈分配</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#递归-vs-非递归"><span class="toc-number">2.3.</span> <span class="toc-text">递归 vs 非递归</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#cin-amp-cout-vs-scanf-amp-printf"><span class="toc-number">2.4.</span> <span class="toc-text">cin&amp;cout vs scanf&amp;printf</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#总结"><span class="toc-number">3.</span> <span class="toc-text">总结</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#16-年-8-月-20-日更新"><span class="toc-number">4.</span> <span class="toc-text">16 年 8 月 20 日更新</span></a></li></ol>
      </div>
    </div>
    
  </aside>
</main>

<!-- disqus 公共JS代码 -->
<script type="text/javascript">
  /* * * CONFIGURATION VARIABLES * * */
  var disqus_shortname = "liu233w";
  var disqus_identifier = "https://liu233w.github.io/2016/07/25/hdu-4825.org/";
  var disqus_url = "https://liu233w.github.io/2016/07/25/hdu-4825.org/";

  isAgent(getDisqus)

  // determine user agent in China
  function isAgent(cb) {
    var url = '//graph.facebook.com/feed?callback=h';
    var xhr = new XMLHttpRequest();
    var called = false;
    xhr.open('GET', url);
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
        called = true;
        cb(true);
      }
    };
    xhr.send();
    // timeout 1s, this facebook API is very fast.
    setTimeout(function () {
      if (!called) {
        xhr.abort();
        cb(false)
      }
    }, 1000);
  }

  function getDisqus(isAgent) {
    var dsq = document.createElement('script');
    dsq.type = 'text/javascript';
    dsq.async = true
    dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq)
  }
</script>
<!-- disqus 公共JS代码 end -->


<script type="text/javascript">
  (function (d, s) {
    var j, e = d.getElementsByTagName(s)[0];

    if (typeof LivereTower === 'function') {
      return;
    }

    j = d.createElement(s);
    j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
    j.async = true;

    e.parentNode.insertBefore(j, e);
  })(document, 'script');
</script>


  <footer>
  <div class="copyright">
    <div>
      &copy; 2019 | Powered by <a href="https://hexo.io" target="_blank">Hexo</a>&nbsp
    </div>
    <div>
      Theme by <a href="https://github.com/lewis-geek/hexo-theme-Aath" target="_blank">Aath</a>
    </div>
  </div>
</footer>


<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script src="/lib/in-view.min.js"></script>
<script src="/lib/lodash.min.js"></script>
<script>
  var isDown = true
  var oldY = 0
  inView.offset(50)

  document.body.addEventListener('touchstart', function(){});
  
  window.addEventListener('scroll', _.throttle(e => {
    var currentY = window.scrollY
    if((oldY - currentY) < 0) {
      isDown = true
    } else {
      isDown = false
    }
    oldY = currentY
  }, 250))

  $("article img").each(function() {
      var strA = "<a data-fancybox='gallery' href='" + this.src + "'></a>";
      $(this).wrapAll(strA);
  });

  $('.toc-link').each(function() {
      var href = $(this).attr("href");
      
      inView(href).on('exit', () => {
        if (isDown) {
          handleActive(href)
        }
      })

      inView(href).on('enter', () => {
        if (!isDown) {
          handleActive(href)
        }
      })

      this.onclick = function(e) {
        var pos = $(href).offset().top - 10;
        $("html,body").animate({scrollTop: pos}, 300);
        setTimeout(() => {
          handleActive(href)
        }, 350)
        return false
      }
  })

  function handleActive(href) {
    document.querySelectorAll('.toc-link').forEach(elm => {
      elm.classList.remove('active')
    })
    document.querySelector(".toc [href='"+ href +"']").classList.add('active')
  }
</script>
<script src="/lib/jquery.fancybox.min.js"></script>

<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>

</body>
</html>
